package com.bckj.fastboot.core.lock;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Aspect
@Component
@ConditionalOnBean(RedissonClient.class)
public class DLockAspect {
    private final RedissonClient redissonClient;

    @Autowired
    public DLockAspect(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @Around("@annotation(dLock)")
    public Object around(ProceedingJoinPoint joinPoint, DLock dLock) throws Throwable {
        String lockName = dLock.value();
        long waitTime = dLock.waitTime();
        long leaseTime = dLock.leaseTime();

        // 获取方法的参数值
        Object[] args = joinPoint.getArgs();

        // 使用SpEL表达式动态生成锁的名称
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("args", args);
        String dynamicLockName = parser.parseExpression(lockName).getValue(context, String.class);

        RLock lock = redissonClient.getLock(dynamicLockName);
        // 等待获取锁
        boolean acquired = lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        if (!acquired) {
            throw new RuntimeException("获取分布式锁失败");
        }
        try {
            return joinPoint.proceed();
        } finally {
            lock.unlock();
        }
    }
}

    
	